using MLSharp.Classification;
using weka.classifiers.trees;
using weka.core;

namespace MLSharp.Weka.Classifiers
{
	/// <summary>
	/// A previously-trained Random Forest that can be used
	/// for new classifications.
	/// </summary>
	public class RandomForestClassifier : IRandomForestClassifier
	{
		#region Private Fields

		/// <summary>
		/// The random forest.
		/// </summary>
		private RandomForest mForest;

		#endregion

		#region Public Constructors

		/// <summary>
		/// Creates an instance with the specified forest.
		/// </summary>
		/// <param name="forest"></param>
		public RandomForestClassifier(RandomForest forest)
		{
			mForest = forest;
		}

		#endregion

		#region Implementation of IClassifier

		/// <summary>
		/// Classifies all the instances in the specified data set.
		/// </summary>
		/// <param name="dataSet">The data set to classify.</param>
		/// <returns>The results of classifying each instance.</returns>
		public ClassificationResult[] Classify(IDataSet dataSet)
		{
			Instances instances = dataSet.ToInstances(true);

			ClassificationResult[] results = new ClassificationResult[dataSet.Instances.Count];

			for (int i=0; i < results.Length; i++)
			{
				ClassificationResult result = new ClassificationResult("", dataSet.Instances[i].ClassValue);
				result.ID = dataSet.Instances[i].Label;

				//The entry with the largest value corresponds to the predicted class.
				double[] distribution = mForest.distributionForInstance(instances.instance(i));

				int maxIndex = 0;

				for (int j=1; j < distribution.Length; j++)
				{
					if (distribution[j] > distribution[maxIndex])
					{
						maxIndex = j;
					}
				}

				result.PredictedClass = dataSet.Attributes[dataSet.TargetAttributeIndex].PossibleValues[maxIndex];
				result.Confidence = distribution[maxIndex];

				results[i] = result;
			}

			return results;
		}

		#endregion
	}
}
